package org.come.bean;

import java.util.ArrayList;
import java.util.List;

import org.come.socket.Agreement;
import org.come.socket.SendMessageUntil;
import org.come.until.GsonUtil;
import org.come.until.Util;

import com.tool.image.ImageMixDeal;
import com.tool.image.ManimgAttribute;

public class Path {
	 private static final int[][] DIREC = {{0, -1},{1, -1},{1, 0},{1, 1},{0, 1},{-1, 1},{-1, 0},{-1, -1}};
	 public static void findPath(byte[][] bs,int x1,int y1,int x2,int y2) {
		  List<Position> openList = new ArrayList<Position>();		 
		  boolean findFlag = false;
	      Position termPos = null;
	      // 起始点
	      Position startPos = new Position(x1, y1, calcH(x1, y1, x2, y2));
	      bs[x1][y1]=3;
	      openList.add(startPos);
	      do {
	          // 通过在开启列表中找到F值最小的点作为当前点
	          Position currentPos = openList.get(0);
	          for (int i = openList.size()-1; i>= openList.size()-9&&i>=0; i--) {
	               if (currentPos.F > openList.get(i).F) {
	                   currentPos = openList.get(i);
	               }
			  }
	          // 将找到的当前点放到关闭列表中，并从开启列表中删除
	          bs[currentPos.row][currentPos.col]=2;
	          openList.remove(currentPos);
	          //1为障碍物 	2为关闭列表的节点 3为开启列表的节点            
	          for (int i = 0; i < DIREC.length; i++) {//遍历当前点对应的8个相邻点
		           int tmpX = currentPos.row + DIREC[i][0];
	               int tmpY = currentPos.col + DIREC[i][1];
	               if (tmpX < 0 || tmpX >= bs.length || tmpY < 0 || tmpY >= bs[0].length||bs[tmpX][tmpY] == 2 ) {
	                   continue;
	               }
                   if (Around_map(i, tmpX, tmpY)) {	
					   bs[tmpX][tmpY]=1;
					   continue;
				   }    					
	               Position tmpPos = new Position(tmpX, tmpY, calcH(tmpX, tmpY, x2, y2), currentPos);
	               //如果不在开启列表中，则加入到开启列表
	               if (bs[tmpX][tmpY]!=3) {	
	                   bs[tmpX][tmpY]=3;
	                   openList.add(tmpPos); 
	               }
	            }    
	            for (int j = openList.size()-1;j>=0&&j>=openList.size()-9 ; j--) {
					if (openList.get(j).row == x2 && openList.get(j).col == y2) {
						termPos = openList.get(j);
						findFlag = true;break;
					}
				}
	        } while(!findFlag&&openList.size() != 0);
	        if(!findFlag) {return;}
		    List<PathPoint> path=new ArrayList<>();
		 if (termPos != null) {
			 PathPoint a=new PathPoint(termPos.row*20+10,termPos.col*20+10);
			 path.add(a);
			 while(termPos.fa != null) {
				 termPos = termPos.fa;
				 if (termPos.fa!= null) {
					 PathPoint a1=new PathPoint(termPos.row*20+10,termPos.col*20+10);
					 path.add(a1);
				 }
			 }
		 }
		 path.set(path.size()-1, new PathPoint(ImageMixDeal.userimg.getRoleShow().getX(), ImageMixDeal.userimg.getRoleShow().getY()));
		 List<PathPoint> paths=PathManage(path);
		    try {
				sendXandYToServer(paths);
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			} 
	    }
		//发送实时坐标给服务端，进行全程遍历
		public static void sendXandYToServer(List<PathPoint> Player_Paths){
			ImageMixDeal.userimg.setMovejiange(0);
			RoleShow roleShow=ImageMixDeal.userimg.getRoleShow();//实例化返回客户端的信息
			roleShow.setPlayer_Paths(Player_Paths);
			RoleMoveBean bean=new RoleMoveBean();
			bean.setPaths(Player_Paths);	
			//创建返回的信息
			String sendMes=Agreement.getAgreement().moveAgreement(GsonUtil.getGsonUtil().getgson().toJson(bean));
			//向服务器发送信息
			SendMessageUntil.toServer(sendMes);	
		} 
	     /**
	     * 计算某个格子的H值
	     * @param x
	     * @param y
	     * @param tx 终点的x值
	     * @param ty 终点的y值
	     * @return
	     */
	    private static int calcH(int x, int y, int tx, int ty) {
	        int diff = Math.abs(x - tx) + Math.abs(y - ty);
	        return diff * 10;
	    }
	    static class Position {
	        public int F;
	        public int G;
	        public int H;
	        public Position fa;
	        public int row;
	        public int col;

	        public Position() {
	        }
	        public Position(int row, int col, int H) {
	            this(row, col, H, null);
	        }

	        public Position(int row, int col, int H, Position pos) {
	        	
	            this.H = H;
	            this.row = row;
	            this.col = col;
	            this.fa = pos;
	            this.G = calcG();
	            this.F = G + H;
	        }

	        /**计算某个点到起始点的代价G*/
	        private int calcG() {
	            if (this.fa == null) {
                    return 0;
                }
	            if (fa.row != this.row && fa.col !=  this.col) {
	                return 14 + fa.G;
	            }
	            return 10 + fa.G;
	        } 

	        public void setFaPos(Position pos) {
	            this.fa = pos;
	            this.G = calcG();
	            this.F = G + H;
	        }

	        @Override
	        public boolean equals(Object obj) {
	            if (obj == null) {
	                return false;
	            }
	            if (!(obj instanceof Position)) {
	                return false;
	            }
	            Position pos = (Position) obj;
	            return this.row == pos.row && this.col == pos.col;
	        }

	        @Override
	        public int hashCode() {
	            final int prime = 31;
	            int result = 1;
	            result = prime * result + row;
	            result = prime * result + col;
	            return result;
	        }

	    }
	    /**
	     * 判断周围节点是否可以通过
	     */
	    public static boolean Around_map(int dir,int tmpx,int tmpy){
			if (Util.mapmodel.mskpanduan(tmpx, tmpy)) {return true;}
			if (dir==0||dir==2||dir==4||dir==6) {
				return false;
			}
			if (dir==1) {
				if (Util.mapmodel.mskpanduan(tmpx+DIREC[6][0],tmpy+DIREC[6][1])
						&&Util.mapmodel.mskpanduan(tmpx+DIREC[4][0],tmpy+DIREC[4][1])) {
					return true;
				}
				return false;
			}else if (dir==3) {
				if (Util.mapmodel.mskpanduan(tmpx+DIREC[0][0],tmpy+DIREC[0][1])
						&&Util.mapmodel.mskpanduan(tmpx+DIREC[6][0],tmpy+DIREC[6][1])) {
					return true;
				}
				return false;
			}else if (dir==5) {
				if (Util.mapmodel.mskpanduan(tmpx+DIREC[0][0],tmpy+DIREC[0][1])
						&&Util.mapmodel.mskpanduan(tmpx+DIREC[2][0],tmpy+DIREC[2][1])) {
					return true;
				}
				return false;
			}else {
				if (Util.mapmodel.mskpanduan(tmpx+DIREC[2][0],tmpy+DIREC[2][1])
						&&Util.mapmodel.mskpanduan(tmpx+DIREC[4][0],tmpy+DIREC[4][1])) {
					return true;
				}
				return false;
			}
	    }
	    public static List<PathPoint> PathManage(List<PathPoint> Player_Paths) {
	    	List<PathPoint> paths=new ArrayList<>();
	    	//增加起始点
	    	int size=Player_Paths.size()-1;
	    	paths.add(Player_Paths.get(size));//增加一个起始点
	    	for (int i = size; i >= 0; i--) {
				PathPoint qidian=Player_Paths.get(i);
	    		for (int j = 0; j < i; j++) {
	    			if (keda(qidian, Player_Paths.get(j))) {
	    				i=j+1;
	    				paths.add(Player_Paths.get(j));
						break;
					}
				}
	    		
			}
	    	return paths;
	    }
		/**
		 * 判断2点直线路径是否可达
		 */
	    public static boolean keda(PathPoint qishi,PathPoint zhongdian){
	        int dir=ChangDir_1(zhongdian.getX()-qishi.getX(),zhongdian.getY()-qishi.getY());
		    int dirs=Playerdir_key(dir, null);
		    PathPoint zjd=qishi;
		    while (zhongdian.getX()!=zjd.getX()||zhongdian.getY()!=zjd.getY()) {
				PathPoint[] premove=PreMove(dirs, zjd);	
				zjd=AreaMin(premove[0],premove[1],qishi, zhongdian); 
				if (!obstacle(zjd)) {
                    return false;
                }
		    }
		    return true;	
	    }
		/**
		 * 判断2点构成的矩形面积大小 放回小的点
		 */
		public static PathPoint AreaMin(PathPoint dian1,PathPoint dian2,PathPoint qishi,PathPoint zhongdian){
			PathPoint min=null;
			if (Area(dian1,qishi,zhongdian)<=Area(dian2, qishi, zhongdian)) {		
				min=dian1;
			}else {
				min=dian2;
			}			
			return min;
				
		}
		
		/**
		 * 求出3点构成的矩形面积
		 */                                
		public static int Area(PathPoint qishi,PathPoint zhongdian,PathPoint danqian){
			    int b=qishi.getX()*(zhongdian.getY()-danqian.getY());
			    int c=zhongdian.getX()*(danqian.getY()-qishi.getY());
			    int a=danqian.getX()*(qishi.getY()-zhongdian.getY());
			    int area=Math.abs(a+b+c);//3点构成矩形面积+
			return area;			
		}
		
		public static boolean obstacle(PathPoint xiayidian){//false为是障碍物	
	    	return !Util.mapmodel.mskpanduan(xiayidian.getX()/20, xiayidian.getY()/20);  	 
	    }
		
		/**
		 * 根据位移偏差判断方向
		 */
		public static int ChangDir_1(int dx,int dy){
			int dir=8;
			if (dx==0&& dy==0) {
				dir=8;
			}else if (dx==0) {
				if (dy>0) {
					dir=4;
				}else {
					dir=0;
				}
				
			}else if (dy==0) {
				if (dx>0) {
					dir=2;
				}else {
					dir=6;
				}
			}else {
				
				int x=Math.abs(dx);
				int y=Math.abs(dy);
				int dir1=0;
				if (x==y) {
					dir1=0;
				}else if (x>y*3) {
					dir1=1;
				}else if (y>x*3) {
					dir1=4;
				}else {
					if (x>y) {
						dir1=2;
					}else {
						dir1=3;
					}
				}
				
				if (dy>0&&dx>0) {
					
					if (dir1==0) {
						dir=3;	
					}else {
						dir=30+dir1;
					}
					
				}else if (dy<0&&dx<0) {
					if (dir1==0) {
						dir=7;	
					}else {
						dir=70+dir1;
					}
				}else if (dy>0&&dx<0) {
					if (dir1==0) {
						dir=5;	
					}else {
						dir=50+dir1;
					}
				}else {
					
					if (dir1==0) {
						dir=1;	
					}else {
						dir=10+dir1;
					}
					
				}
				
			} 
			
			
			return dir;
		}
		
		/**
		 * 与终点插肩而过
		 */
		public static boolean panduan(int dir_1,PathPoint danqian,PathPoint zhongdian){
			
			int dir=ChangDir_1(zhongdian.getX()-danqian.getX(),
					zhongdian.getY()-danqian.getY());
			switch (dir_1) {
			case 0:
			case 1:
			case 2:
			case 3:
			case 4:
		    case 5:
			case 6:
			case 7:
				if (dir==dir_1) {
					return true;
				}
				break;
				case 11:
					if (dir==2||dir==11||dir==12) {
						return true;
					}
				break;
				case 12:
				case 13:				
					if (dir==11||dir==12||dir==13||dir==1) {
						return true;
					}break;
				case 14:
					if (dir==0||dir==13||dir==14) {
						return true;
					}break;
				case 31:
					if (dir==2||dir==31||dir==32) {
						return true;
					}break;
				case 32:
				case 33:
					if (dir==31||dir==32||dir==33||dir==3) {
						return true;
					}break;
				case 34:
					if (dir==4||dir==33||dir==34) {
						return true;
					}break;
				case 51:
					if (dir==6||dir==51||dir==52) {
						return true;
					}break;
				case 52:
				case 53:
					if (dir==51||dir==52||dir==53||dir==5) {
						return true;
					}break;
				case 54:
					if (dir==4||dir==53||dir==54) {
						return true;
					}break;
				case 71:
					if (dir==6||dir==71||dir==72) {
						return true;
					}break;
				case 72:
				case 73:
					if (dir==71||dir==72||dir==73||dir==7) {
						return true;
					}break;
				case 74:
					if (dir==0||dir==73||dir==74) {
						return true;
					}break;
			default:
				break;
			}
			
			return false;
		}
		
		/**
		 * 根据方向给出2个预移动点
		 */
		public static  PathPoint[] PreMove(int dir,PathPoint pathPoint){
			PathPoint[] points=new PathPoint[2];
	       
			int x=pathPoint.getX();
			int y=pathPoint.getY();
			switch (dir) {
			case 0:
				points[0]=new PathPoint(x, y-1);
				points[1]=new PathPoint(x, y-1);			
				break;
			case 1:
				points[0]=new PathPoint(x+1, y-1);
				points[1]=new PathPoint(x+1, y-1);			
				break;
			case 2:
			    points[0]=new PathPoint(x+1, y);
				points[1]=new PathPoint(x+1, y);			
				break;
			case 3:
				points[0]=new PathPoint(x+1, y+1);
				points[1]=new PathPoint(x+1, y+1);
				
				break;
			case 4:
				points[0]=new PathPoint(x, y+1);
				points[1]=new PathPoint(x, y+1);	
				break;
			case 5:
				points[0]=new PathPoint(x-1, y+1);
				points[1]=new PathPoint(x-1, y+1);
				break;
			case 6:
				points[0]=new PathPoint(x-1, y);
				points[1]=new PathPoint(x-1, y);
				break;
			case 7:
				points[0]=new PathPoint(x-1, y-1);
				points[1]=new PathPoint(x-1, y-1);
				break;
				case 12:
				points[0]=new PathPoint(x, y-1);
				points[1]=new PathPoint(x+1, y-1);
				break;
				case 11:
				points[0]=new PathPoint(x+1, y-1);
			    points[1]=new PathPoint(x+1, y);
					break;
				case 31:
				points[0]=new PathPoint(x+1, y);
				points[1]=new PathPoint(x+1, y+1);
					break;
				case 32:
				points[0]=new PathPoint(x+1, y+1);
				points[1]=new PathPoint(x, y+1);
					break;
				case 52:
					points[0]=new PathPoint(x, y+1);
					points[1]=new PathPoint(x-1, y+1);
					break;
				case 51:
					points[0]=new PathPoint(x-1, y+1);
					points[1]=new PathPoint(x-1, y);
					break;
				case 71:
					points[0]=new PathPoint(x-1, y);
					points[1]=new PathPoint(x-1, y-1);
					break;
				case 72:
					points[0]=new PathPoint(x-1, y-1);
					points[1]=new PathPoint(x, y-1);
					break;
			default:
				break;
			}
			
			
			return points;		
		} 
		/**
		 * 根据方向调整人物方向
		 * @param
		 * 
		 */
		public static int Playerdir_key(int dir, ManimgAttribute manmove){
			
			switch (dir) {
			case 0:
			case 1:
	        case 2:
	        case 3:
	        case 4:
	        case 5:
	        case 6:
	        case 7:
	        	return dir;
	        case 11:
	        	return 11;
	        case 12:
	        	return 11;
	        case 13:
	        	return 12;
	        case 14:
	        	return 12;
	        case 31:
	        	return 31;
	        case 32:
	        	return 31;
	        case 33:
	        	return 32;
	        case 34:
	        	return 32;
	        case 51:
	        	return 51;
	        case 52:
	        	return 51;
	        case 53:
	        	return 52;
	        case 54:
	        	return 52;
	        case 71:
	        	return 71;
	        case 72:
	        	return 71;
	        case 73:
	        	return 72;
	        case 74:
	        	return 72;
	        default:
				break;
			}
			return dir;
		}
}